package com.yzd.learnjava.concurrency;

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import com.yzd.learnjava.util.Print;

public class NotifyVsNotifyAll {
	public static void main(String[] args) throws InterruptedException {
		ExecutorService exec = Executors.newCachedThreadPool();
		for(int i = 0 ; i < 5 ; i++) {
			exec.execute(new Task());
		}
		exec.execute(new Task2());
		Timer timer = new Timer();
		timer.scheduleAtFixedRate(new TimerTask() {
			boolean prod = true;
			@Override
			public void run() {
				if(prod) {
					Print.print("\nnotify");
					Task.blocker.prod();
					prod = false ;
				} else {
					Print.print("\nnotifyAll");
					Task.blocker.prodAll();
					prod = true;
				}
			}
		}, 400, 400);
		
		TimeUnit.SECONDS.sleep(5);
		timer.cancel();
		Print.print("Timer canceled");
		
		TimeUnit.MILLISECONDS.sleep(500);
		Print.print("Task2.blocker.prodALL()");
		Task2.blocker.prodAll();
		
		TimeUnit.MILLISECONDS.sleep(500);
		Print.print("\nshutting down");
		exec.shutdown();
	}
}

class Blocker {
	synchronized void waitingCall() {
		try {
			while(!Thread.interrupted()) {
				wait();
				Print.print(Thread.currentThread() + " ");
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	synchronized void prod() {
		notify();
	}
	
	synchronized void prodAll() {
		notifyAll();
	}
}

class Task implements Runnable{
	static Blocker blocker = new Blocker();
	public void run() {
		blocker.waitingCall();
	}
}

class Task2 implements Runnable{
	static Blocker blocker = new Blocker();
	public void run() {
		blocker.waitingCall();
	}
}


